package com.gmrz.webauthn.common;

import com.gmrz.service.challengestore.ChallengeStoreException;
import com.gmrz.service.challengestore.ChallengeStoreService;
import com.gmrz.uaf.common.GuiceUtil;
import com.gmrz.uaf.db.DAOException;
import com.gmrz.uaf.db.UAFDAOFactory;
import com.gmrz.uaf.db.UAFDBConnectionMgr;
import com.gmrz.uaf.protocol.v1.processor.exception.UAFErrorCode;
import com.gmrz.uaf.server.ServerConfig;
import com.gmrz.util.Strings;
import com.gmrz.webauthn.db.dao.TenantConfigDAO;
import com.gmrz.webauthn.db.dao.WebAuthnMetadataDAO;
import com.gmrz.webauthn.protocol.v1.schema.TenantConfig;
import com.gmrz.webauthn.protocol.v1.schema.WebAuthenticatorSpec;
import com.gmrz.webauthn.protocol.v1.schema.WebAuthnMetadata;
import com.google.gson.Gson;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Set;

public class WebAuthnConstants {

    //渠道配置相关参数
    private static final String[] WEBAUTN_TENANT_CONFIG_ENAMES = new String[]{"webauthn.authenticator.selection.criteria.authenticator.attachment"
            , "webauthn.authenticator.selection.criteria.require.residentkey"
            , "webauthn.authenticator.selection.criteria.user.verification"};

    public static final String WEBAUTHN_AUTHENTICATOR_SELECTION_CRITERIA_AUTHENTICATOR_ATTACHMENT = "webauthn.authenticator.selection.criteria.authenticator.attachment";
    public static final String WEBAUTHN_AUTHENTICATOR_SELECTION_CRITERIA_REQUIRE_RESIDENTKEY = "webauthn.authenticator.selection.criteria.require.residentkey";
    public static final String WEBAUTHN_AUTHENTICATOR_SELECTION_CRITERIA_USER_VERIFICATION = "webauthn.authenticator.selection.criteria.user.verification";
    public static final String WEBAUTHN_AUTH_STRICTMODE = "webauthn.auth.strictmode";
    public static final String WEBAUTHN_AUTH_ANONYMOUS = "webauthn.auth.anonymous";
    public static final String WEBAUTHN_AUTHENTICATOR_SELECTION_CRITERIA_AUTHENTICATOR_ATTESTATION = "webauthn.authenticator.selection.criteria.authenticator.attestation";

    public static final String WEBAUTH_ANONYMOUS_AUTHENTICATOR = "00000000000000000000000000000000";

    public static final String WEBAUTH_USER_VERIFICATION_REQUIRED = "required";

    public static final String WEBAUTHN_AUTHENTICATOR_RPID = "webauthn.authenticator.rpid";
    public static final String WEBAUTHN_AUTHENTICATOR_RPNAME = "webauthn.authenticator.rpname";

    public static final String WEBAUTHN_AUTHENTICATOR_TIME_OUT = "webauthn.authenticator.timeout";
    public static final String WEBAUTHN_AUTHENTICATOR_EXTENSIONS = "webauthn.authenticator.extensions";

    public static enum AttestationResult
    {
        SUCCESS(0),  FAILED(1),  UNAVAILABLE(2);

        private int value;

        private AttestationResult(int value)
        {
            this.value = value;
        }

        public int getValue()
        {
            return this.value;
        }
    }

    /**
     * 根据配置名称和渠道名称获取配置内容
     *
     * @param configName 配置名称
     * @param tenantId   渠道名称
     * @return 配置内容
     * @throws DAOException
     * @throws ChallengeStoreException
     * @throws SQLException
     */
    public static String getTenantConfigContent(String configName, String tenantId) throws DAOException, ChallengeStoreException, SQLException {
        ServerConfig serverConfig = GuiceUtil.getProcessorInjector().getInstance(ServerConfig.class);
        return serverConfig.getConfigByTenantId(configName,tenantId);
    }


    public static Set<String> getAaguidInPolicy(String tenantId, String authType, String transType) throws DAOException, ChallengeStoreException, SQLException {
        ChallengeStoreService challengeStoreService = GuiceUtil.getProcessorInjector().getInstance(ChallengeStoreService.class);

        String cacheKey = "webauthn.policy." + tenantId + "." + authType + "." + transType;

        Set<String> aaguids = challengeStoreService.smembers(cacheKey);

        //如果缓存中不存在，则从数据库中获取并存入缓存
        if (aaguids.isEmpty()) {
            Connection conn = UAFDBConnectionMgr.getConnection();
            WebAuthnMetadataDAO webAuthnMetadataDAO = UAFDAOFactory.createWebAuthnMetadataDAO(conn);
            aaguids = webAuthnMetadataDAO.findAaguidArr(tenantId, authType, transType);

            for (String value : aaguids) {
                challengeStoreService.sadd(cacheKey, value);
            }
        }

        return aaguids;
    }

    public static WebAuthnMetadata getWebAuthenticatorSpec(String aaguid) throws ChallengeStoreException, SQLException, DAOException {

        ChallengeStoreService challengeStoreService = GuiceUtil.getProcessorInjector().getInstance(ChallengeStoreService.class);

        String cacheKey = "uaf.webauthn.policy.aaguid." + aaguid;
        String value = challengeStoreService.getRedisValue(cacheKey);
        if(null == value){
            Connection conn = UAFDBConnectionMgr.getConnection();
            WebAuthnMetadataDAO webAuthnMetadataDAO = UAFDAOFactory.createWebAuthnMetadataDAO(conn);
            WebAuthnMetadata webAuthnMetadata = webAuthnMetadataDAO.findByAAGUID(aaguid);
            if(null != webAuthnMetadata) {
                Gson gson = new Gson();
                challengeStoreService.putString(cacheKey, gson.toJson(webAuthnMetadata));
            }
            return webAuthnMetadata;
        }else {
            Gson gson = new Gson();
            WebAuthnMetadata webAuthnMetadata = gson.fromJson(value,WebAuthnMetadata.class);
            return webAuthnMetadata;
        }

    }
}
